package com.weimob.mcloud.wechatwork.customer.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.FollowUserBO;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.CustomerTag;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.Tag;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.TagDetail;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.TagGroup;
import com.weimob.mcloud.wechatwork.customer.convertor.tag.CustomerTagCovert;
import com.weimob.mcloud.wechatwork.customer.externalDependencyProxy.usermanagement.EmployeeProxy;
import com.weimob.mcloud.wechatwork.customer.mq.product.TagChangeMsgProduct;
import com.weimob.mcloud.wechatwork.customer.service.CustomerEmployeeTagService;
import com.weimob.mcloud.wechatwork.customer.service.CustomerTagSyncService;
import com.weimob.mcloud.wechatwork.customer.service.TagBaseService;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.tag.v2.CorpTagDTO;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.tag.v2.CorpTagGroupDTO;
import com.weimob.mcloud.wechatwork.customer.service.user.module.msgBody.CorpCustomerTagChangeBody;
import com.weimob.mcloud.wechatwork.customer.third.customer.CustomerThird;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class CustomerTagSyncServiceImpl implements CustomerTagSyncService {


    @Autowired
    private CustomerThird customerThird;

    @Autowired
    private CustomerEmployeeTagService customerEmployeeTagService;

    @Autowired
    private TagBaseService tagBaseService;

    @Autowired
    private TagChangeMsgProduct tagChangeMsgProduct;

    @Autowired
    private EmployeeProxy employeeProxy;

    /**
     * 客户标签同步,以员工维度同步
     *
     * @param privateSphere 私域信息
     * @param txCustomerId  企微客户id
     * @param customerWid           从passport查询到的客户wid
     * @param txUserList   企微官方与该客户拥有好友关系的所有员工给该客户打的标签信息
     * @param employee      要处理给该客户打标签的当前员工
     * @return
     */
    @Override
    public Boolean syncCustomerTag(PrivateSphere privateSphere, String txCustomerId, Long customerWid, List<FollowUserBO> txUserList, Employee employee) {
        //1、必要参数校验
        if (null == privateSphere || StringUtils.isBlank(txCustomerId)
                || CollectionUtils.isEmpty(txUserList) || null == employee) {
            return false;
        }
        String id = employee.getId();
        String txUserId = employee.getTxUserId();
        if (StringUtils.isBlank(txUserId) && StringUtils.isBlank(id)) {
            return false;
        }

        //2、根据orgUserId查询员工信息，判断企微助手有没有落员工数据
        if (StringUtils.isBlank(id) || StringUtils.isBlank(txUserId)) {

            employee= employeeProxy.fetchEmployeeById(privateSphere, txUserId, id,false,false);
            if (Objects.isNull(employee) || StringUtils.isBlank(id) || StringUtils.isBlank(txUserId)) {
                log.error("根据腾讯userId查询企微助手员工主键id失败, corpId:{}, externalUserId:{}, currentTXUserId:{}",
                        privateSphere.getCorpId(), txCustomerId, txUserId);
                return false;
            }
        }

        if (null == customerWid) {
            //3、根据externalUserId换wid
            customerWid = customerThird.getSuperWid(privateSphere.getBosId(), txCustomerId, privateSphere.getCorpId());
            if (null == customerWid) {
                log.warn("客户标签同步，查询passport获取wid失败, externalUserId:{}", txCustomerId);
                return false;
            }
        }

        //4、根据externalUserId、orgUserId查询该员工给该客户打的所有标签
        List<TagDetail> tagDetailList = customerEmployeeTagService.fetchCustomerEmployeeTag(privateSphere, txCustomerId, id, false);
        List<String> qwDBTagIds = CustomerTagCovert.toTagIds(tagDetailList);

        //5、分析当前员工给该客户的打标数据，如果抽取不到，则是传参有问题，直接结束处理流程
        FollowUserBO analysisUserBO = analysisUserBO(txUserList, txUserId);
        if (null == analysisUserBO) {
            return false;
        }

        //6、查询腾讯返回的 该员工给该客户打的所有标签
        List<String> txQueryTagIds = CustomerTagCovert.toTagIdsFromAnalysisUserBO(analysisUserBO.getTags());

        //7、判断企微助手db里存的员工给该客户打的标签数据和查询腾讯侧返回的标签数据是否一样
        Boolean isSame = compareSame(qwDBTagIds, txQueryTagIds);
        if (!isSame) {
            //如果有差异，企微助手db更新或者添加
            if (CollectionUtils.isEmpty(tagDetailList)) {
                customerEmployeeTagService.saveCustomerEmployeeTag(privateSphere, txCustomerId, id, txQueryTagIds);
            } else {
                customerEmployeeTagService.updateCustomerEmployeeTag(privateSphere, txCustomerId, id, txQueryTagIds);
            }

        }

        //8、查询客户标签表，不含员工
        CustomerTag customerTag = customerEmployeeTagService.getCustomerTag(privateSphere, txCustomerId);
        Set<String> qwDBCustomerAllTagIds = new HashSet<>();
        if (null != customerTag && CollectionUtils.isNotEmpty(customerTag.getTagIds())) {
            qwDBCustomerAllTagIds.addAll(customerTag.getTagIds());
        }

        //9、查询腾讯腾讯，腾讯返回的客户身上的所有标签
        Set<String> txQueryCustomerAllTagIds = CustomerTagCovert.toTagIdsFromTXUserList(txUserList);

        //10、企微助手db里的标签数据和查询腾讯返回的标签数据做对比，获取要添加的标签
        Set<String> addTagIds = analysisAddTagIds(qwDBCustomerAllTagIds, txQueryCustomerAllTagIds);

        //11、企微助手db里的标签数据和查询腾讯返回的标签数据做对比，获取要添加的标签
        Set<String> removeTagIds = analysisRemoveTagIds(qwDBCustomerAllTagIds, txQueryCustomerAllTagIds);

        //12、如果查询企微官方返回的标签和企微助手db存的标签数据有差异，企微助手本地覆盖更新客户标签表(该表里的标签数据不需要顺序),通知cdp客户标签变更
        if (CollectionUtils.isNotEmpty(addTagIds) || CollectionUtils.isNotEmpty(removeTagIds)) {

            //企微助手本地添加或者更新客户标签表(该表里的标签数据不需要顺序)
            if (CollectionUtils.isEmpty(qwDBCustomerAllTagIds)) {
                customerEmployeeTagService.saveCustomerTag(privateSphere, txCustomerId, Lists.newArrayList(txQueryCustomerAllTagIds));
            } else {
                customerEmployeeTagService.updateCustomerTag(privateSphere, txCustomerId, Lists.newArrayList(txQueryCustomerAllTagIds));
            }

            //如果企微官方的标签和企微助手里面的标签数据有差异，就通知cdp添加或者移除
            sendCustomerTagChangeMsg(privateSphere, customerWid, txCustomerId, employee, addTagIds, removeTagIds);
        }

        return true;
    }

    /**
     * 如果腾讯侧有的，企微助手db里没有的，则返回
     *
     * @param qwDBCustomerAllTagIds 企微助手db里面存的客户标签数据
     * @param txCustomerAllTagIds   腾讯侧有的客户所有的标签数据
     * @return
     */
    private Set<String> analysisAddTagIds(Set<String> qwDBCustomerAllTagIds, Set<String> txCustomerAllTagIds) {
        if (CollectionUtils.isEmpty(txCustomerAllTagIds)) {
            return new HashSet<>();
        }

        if (CollectionUtils.isEmpty(qwDBCustomerAllTagIds)) {
            return txCustomerAllTagIds;
        }

        Set<String> addTagIds = new HashSet<>();
        for (String txTagId : txCustomerAllTagIds) {
            if (!qwDBCustomerAllTagIds.contains(txTagId)) {
                addTagIds.add(txTagId);
            }
        }

        return addTagIds;
    }

    /**
     * 如果企微助手db里面有客户标签数据，腾讯侧没有该标签数据，则返回
     *
     * @param qwDBCustomerAllTagIds 企微助手db里存的客户的所有的标签数据
     * @param txCustomerAllTagIds   腾讯侧有的客户的所有的标签数据
     * @return
     */
    private Set<String> analysisRemoveTagIds(Set<String> qwDBCustomerAllTagIds, Set<String> txCustomerAllTagIds) {
        if (CollectionUtils.isEmpty(qwDBCustomerAllTagIds)) {
            return new HashSet<>();
        }

        if (CollectionUtils.isEmpty(txCustomerAllTagIds)) {
            return qwDBCustomerAllTagIds;
        }

        Set<String> removeTagIds = new HashSet<>();
        for (String qwTagId : qwDBCustomerAllTagIds) {
            if (!txCustomerAllTagIds.contains(qwTagId)) {
                removeTagIds.add(qwTagId);
            }
        }

        return removeTagIds;
    }

    private Boolean compareSame(List<String> qwDBTagIdList, List<String> txQueryTagIdList) {
        if (CollectionUtils.isEmpty(qwDBTagIdList) && CollectionUtils.isEmpty(txQueryTagIdList)) {
            return true;
        }

        if (CollectionUtils.isEmpty(qwDBTagIdList) || CollectionUtils.isEmpty(txQueryTagIdList)) {
            return false;
        }

        if (qwDBTagIdList.size() != txQueryTagIdList.size()) {
            return false;
        }

        qwDBTagIdList.sort(null);
        txQueryTagIdList.sort(null);

        for (int i = 0; i < qwDBTagIdList.size(); i++) {
            if (!Objects.equals(qwDBTagIdList.get(i), txQueryTagIdList.get(i))) {
                return false;
            }
        }

        return true;
    }

    private FollowUserBO analysisUserBO(List<FollowUserBO> followUsers, String currentTXUserId) {
        if (CollectionUtils.isEmpty(followUsers) || StringUtils.isBlank(currentTXUserId)) {
            return null;
        }

        for (FollowUserBO followUserBO : followUsers) {
            String userId = followUserBO.getUserid();
            if (currentTXUserId.equals(userId)) {
                return followUserBO;
            }
        }

        return null;
    }

    private void sendCustomerTagChangeMsg(PrivateSphere privateSphere, Long wid, String externalUserId, Employee employee,
                                          Set<String> addTagIds, Set<String> removeTagIds) {
        if (null == privateSphere || null == wid || StringUtils.isBlank(externalUserId) || null == employee) {
            return;
        }

        if (CollectionUtils.isEmpty(addTagIds) && CollectionUtils.isEmpty(removeTagIds)) {
            return;
        }

        Set<String> allTagIds = new HashSet<>();
        if (CollectionUtils.isNotEmpty(addTagIds)) {
            allTagIds.addAll(addTagIds);
        }
        if (CollectionUtils.isNotEmpty(removeTagIds)) {
            allTagIds.addAll(removeTagIds);
        }

        //根据标签id查询标签组
        List<Tag> tagList = tagBaseService.queryTagByTagIds(privateSphere.getCorpId(), Lists.newArrayList(allTagIds), true);
        if (CollectionUtils.isEmpty(tagList)) {
            log.warn("同步cdp客户标签变更, 查询标签不存在, corpId:{}, tagIds:{}", privateSphere.getCorpId(), JSON.toJSONString(allTagIds));
            return;
        }

        Map<String, String> tagIdAndGroupIdMap = toTagIdAndGroupIdMap(tagList);

        //构建需要添加的标签对象
        List<CorpTagDTO> addCorpTagDTOS = buildCorpTagDTOList(addTagIds, tagIdAndGroupIdMap);

        //构建需要移除的标签对象
        List<CorpTagDTO> removeCorpTagDTOS = buildCorpTagDTOList(removeTagIds, tagIdAndGroupIdMap);


        CorpCustomerTagChangeBody corpCustomerTagChangeBody = new CorpCustomerTagChangeBody();
        corpCustomerTagChangeBody.setBosId(privateSphere.getBosId());
        corpCustomerTagChangeBody.setCorpId(privateSphere.getCorpId());
        corpCustomerTagChangeBody.setExternalUserId(externalUserId);
        corpCustomerTagChangeBody.setWid(wid);
        corpCustomerTagChangeBody.setTxUserId(employee.getTxUserId());
        corpCustomerTagChangeBody.setOrgUserId(employee.getId());
        corpCustomerTagChangeBody.setAddTagList(addCorpTagDTOS);
        corpCustomerTagChangeBody.setRemoveTagList(removeCorpTagDTOS);

        //同步cdp添加客户标签关系
        tagChangeMsgProduct.sendCorpCustomerTagChangeBody(corpCustomerTagChangeBody);
    }

    private Map<String, String> toTagIdAndGroupIdMap(List<Tag> tagIdList) {
        if (CollectionUtils.isEmpty(tagIdList)) {
            return new HashMap<>();
        }

        Map<String, String> tagIdAndGroupIdMap = new HashMap<>();
        for (Tag tag : tagIdList) {
            TagGroup tagGroup = tag.getTagGroup();
            if (null == tagGroup) {
                continue;
            }

            tagIdAndGroupIdMap.put(tag.getExternalTagId(), tagGroup.getExternalTagGroupId());
        }

        return tagIdAndGroupIdMap;
    }

    private List<CorpTagDTO> buildCorpTagDTOList(Set<String> tagIds, Map<String, String> tagIdAndGroupIdMap) {
        if (CollectionUtils.isEmpty(tagIds) || MapUtils.isEmpty(tagIdAndGroupIdMap)) {
            return new ArrayList<>();
        }

        List<CorpTagDTO> list = new ArrayList<>();
        for (String tagId : tagIds) {
            String groupId = tagIdAndGroupIdMap.get(tagId);
            if (StringUtils.isBlank(groupId)) {
                continue;
            }

            CorpTagDTO corpTagDTO = new CorpTagDTO();
            corpTagDTO.setCorpTagId(tagId);

            CorpTagGroupDTO tagGroupDTO = new CorpTagGroupDTO();
            tagGroupDTO.setCorpTagGroupId(groupId);
            corpTagDTO.setTagGroupDTO(tagGroupDTO);

            list.add(corpTagDTO);
        }

        return list;
    }
}
